பைத்தானின் asyncio குறைந்த-நிலை நெட்வொர்க்கிங்கை மாஸ்டர் செய்யுங்கள். இந்த ஆழமான டைவ் டிரான்ஸ்போர்ட்கள் மற்றும் நெறிமுறைகளை உள்ளடக்கியது, உயர் செயல்திறன் கொண்ட, தனிப்பயன் நெட்வொர்க் பயன்பாடுகளை உருவாக்குவதற்கான நடைமுறை எடுத்துக்காட்டுகளுடன்.
பைத்தானின் Asyncio டிரான்ஸ்போர்ட்டை தெளிவுபடுத்துதல்: குறைந்த-நிலை நெட்வொர்க்கிங்கில் ஒரு ஆழமான மூழ்கல்
நவீன பைதான் உலகில், asyncio
உயர் செயல்திறன் நெட்வொர்க் நிரலாக்கத்தின் மூலக்கல்லாக மாறியுள்ளது. டெவலப்பர்கள் பெரும்பாலும் அதன் அழகான உயர்-நிலை APIகளுடன் தொடங்குகிறார்கள், async
மற்றும் await
ஐ aiohttp
அல்லது FastAPI
போன்ற லைப்ரரிகளுடன் பயன்படுத்தி பதிலளிக்கக்கூடிய பயன்பாடுகளை குறிப்பிடத்தக்க எளிதில் உருவாக்கலாம். StreamReader
மற்றும் StreamWriter
பொருள்கள், asyncio.open_connection()
போன்ற செயல்பாடுகளால் வழங்கப்படுகின்றன, நெட்வொர்க் I/O ஐ கையாள ஒரு அருமையான எளிய, தொடர்ச்சியான வழியை வழங்குகின்றன. ஆனால் சுருக்கம் போதுமானதாக இல்லாதபோது என்ன நடக்கும்? ஒரு சிக்கலான, நிலைத்தன்மையுள்ள அல்லது தரமற்ற நெட்வொர்க் புரோட்டோகாலை நீங்கள் செயல்படுத்த வேண்டியிருந்தால் என்ன செய்வது? அண்டர்லயிங் இணைப்பை நேரடியாகக் கட்டுப்படுத்துவதன் மூலம் ஒவ்வொரு கடைசி செயல்திறன் துளியையும் நீங்கள் கசக்கிப் பிழிய வேண்டியிருந்தால் என்ன செய்வது? இதுதான் asyncio இன் நெட்வொர்க்கிங் திறன்களின் உண்மையான அடித்தளம் உள்ளது: குறைந்த-நிலை போக்குவரத்து மற்றும் நெறிமுறை API. முதலில் மிரட்டுவது போல் தோன்றினாலும், இந்த சக்திவாய்ந்த இரட்டையரைப் புரிந்துகொள்வது புதிய அளவிலான கட்டுப்பாடு மற்றும் நெகிழ்வுத்தன்மையைத் திறக்கிறது, இது நீங்கள் கற்பனை செய்யக்கூடிய எந்தவொரு நெட்வொர்க் பயன்பாட்டையும் உருவாக்க உதவுகிறது. இந்த விரிவான வழிகாட்டி சுருக்க அடுக்குகளை உரித்து, போக்குவரத்து மற்றும் நெறிமுறைகளுக்கு இடையிலான கூட்டுறவு உறவை ஆராய்ந்து, பைத்தானில் குறைந்த-நிலை ஒத்திசைவற்ற நெட்வொர்க்கிங்கை நீங்கள் மாஸ்டர் செய்ய அதிகாரம் அளிக்கும் நடைமுறை எடுத்துக்காட்டுகளின் மூலம் உங்களை அழைத்துச் செல்லும்.
Asyncio நெட்வொர்க்கிங்கின் இரண்டு முகங்கள்: உயர்-நிலை vs. குறைந்த-நிலை
குறைந்த-நிலை APIகளில் நாம் ஆழமாக மூழ்குவதற்கு முன், asyncio சுற்றுச்சூழல் அமைப்பில் அவற்றின் இடத்தைப் புரிந்துகொள்வது மிகவும் முக்கியமானது. Asyncio புத்திசாலித்தனமாக நெட்வொர்க் தகவல்தொடர்புக்கு இரண்டு தனித்தனி அடுக்குகளை வழங்குகிறது, ஒவ்வொன்றும் வெவ்வேறு பயன்பாட்டு நிகழ்வுகளுக்கு ஏற்றது.
உயர்-நிலை API: ஸ்ட்ரீம்கள்
உயர்-நிலை API, பொதுவாக "ஸ்ட்ரீம்கள்" என்று குறிப்பிடப்படுகிறது, இது பெரும்பாலான டெவலப்பர்கள் முதலில் சந்திக்கும் ஒன்றாகும். நீங்கள் asyncio.open_connection()
அல்லது asyncio.start_server()
ஐப் பயன்படுத்தும்போது, StreamReader
மற்றும் StreamWriter
பொருட்களைப் பெறுவீர்கள். இந்த API எளிமை மற்றும் பயன்பாட்டின் எளிமைக்காக வடிவமைக்கப்பட்டுள்ளது.
- கட்டாய பாணி: இது தொடர்ச்சியான குறியீட்டை எழுத உங்களை அனுமதிக்கிறது. 100 பைட்களைப் பெற நீங்கள்
await reader.read(100)
மற்றும் பதில அனுப்பwriter.write(data)
செய்கிறீர்கள். இந்தasync/await
முறை உள்ளுணர்வு மற்றும் காரணத்திற்கு எளிதானது. - வசதியான உதவியாளர்கள்: இது
readuntil(separator)
மற்றும்readexactly(n)
போன்ற முறைகளை வழங்குகிறது, அவை பொதுவான ஃப்ரேமிங் பணிகளைக் கையாளுகின்றன, இதனால் நீங்கள் கைமுறையாக இடையகங்களை நிர்வகிப்பதிலிருந்து காப்பாற்றப்படுகிறீர்கள். - சிறந்த பயன்பாட்டு வழக்குகள்: எளிய கோரிக்கை-பதில் புரோட்டோக்கால்கள் (அடிப்படை HTTP கிளையண்ட் போன்றவை), வரி அடிப்படையிலான புரோட்டோக்கால்கள் (Redis அல்லது SMTP போன்றவை) அல்லது தொடர்பு ஒரு கணிக்கக்கூடிய, நேரியல் ஓட்டத்தைப் பின்பற்றும் எந்தவொரு சூழ்நிலைக்கும் ஏற்றது.
இருப்பினும், இந்த எளிமை ஒரு வர்த்தகத்துடன் வருகிறது. ஒரே நேரத்தில் படிக்க மற்றும் எழுத அல்லது சிக்கலான இணைப்பு நிலைகளை நிர்வகிக்க தொடர்ச்சியான await
மாதிரி கடினமாக்கக்கூடிய அதிக அளவு ஒரே நேரத்தில், நிகழ்வு-உந்துதல் நெறிமுறைகளுக்கு ஸ்ட்ரீம் அடிப்படையிலான அணுகுமுறை குறைவான செயல்திறன் கொண்டது.
குறைந்த-நிலை API: டிரான்ஸ்போர்ட்கள் மற்றும் நெறிமுறைகள்
இது உயர்-நிலை ஸ்ட்ரீம்கள் API உண்மையில் கட்டப்பட்ட அடித்தள அடுக்கு ஆகும். குறைந்த-நிலை API போக்குவரத்து மற்றும் நெறிமுறைகள் என இரண்டு தனித்தனி கூறுகளை அடிப்படையாகக் கொண்ட ஒரு வடிவமைப்பு முறையைப் பயன்படுத்துகிறது.
- நிகழ்வு-உந்துதல் பாணி: தரவைப் பெற நீங்கள் ஒரு செயல்பாட்டை அழைப்பதற்குப் பதிலாக, நிகழ்வுகள் நிகழும்போது asyncio உங்கள் பொருளில் உள்ள முறைகளை அழைக்கிறது (எ.கா., இணைப்பு ஏற்படுத்தப்பட்டது, தரவு பெறப்பட்டது). இது ஒரு திரும்ப அழைப்பு அடிப்படையிலான அணுகுமுறை.
- கவலைகளின் பிரிவு: இது "என்ன" என்பதை "எப்படி" என்பதிலிருந்து சுத்தமாகப் பிரிக்கிறது. நெறிமுறை தரவைக் கொண்டு என்ன செய்வது என்று வரையறுக்கிறது (உங்கள் பயன்பாட்டு தர்க்கம்), அதே நேரத்தில் டிரான்ஸ்போர்ட் தரவை எவ்வாறு அனுப்புவது மற்றும் பெறுவது என்பதை கையாளுகிறது (I/O பொறிமுறையை).
- அதிகபட்ச கட்டுப்பாடு: இந்த API இடையகப்படுத்துதல், ஓட்டக் கட்டுப்பாடு (பின் அழுத்தம்) மற்றும் இணைப்பு வாழ்க்கைச் சுழற்சி ஆகியவற்றின் மீது உங்களுக்கு நல்ல கட்டுப்பாட்டைக் கொடுக்கிறது.
- சிறந்த பயன்பாட்டு வழக்குகள்: தனிப்பயன் பைனரி அல்லது டெக்ஸ்ட் புரோட்டோக்கால்களை செயல்படுத்துவதற்கும், ஆயிரக்கணக்கான நிலையான இணைப்புகளைக் கையாளும் உயர் செயல்திறன் சேவையகங்களை உருவாக்குவதற்கும் அல்லது நெட்வொர்க் கட்டமைப்புகள் மற்றும் லைப்ரரிகளை உருவாக்குவதற்கும் அவசியம்.
இதை இப்படி நினைத்துப் பாருங்கள்: ஸ்ட்ரீம்ஸ் API என்பது உணவு கிட் சேவையை ஆர்டர் செய்வது போன்றது. நீங்கள் முன்-பகுதியளவு பொருட்கள் மற்றும் பின்பற்ற ஒரு எளிய செய்முறையைப் பெறுவீர்கள். டிரான்ஸ்போர்ட் மற்றும் புரோட்டோகால் API என்பது மூலப்பொருட்கள் மற்றும் செயல்முறையின் ஒவ்வொரு அடியிலும் முழு கட்டுப்பாட்டுடன் ஒரு தொழில்முறை சமையலறையில் ஒரு சமையல்காரர் போன்றது. இரண்டுமே ஒரு சிறந்த உணவை உருவாக்க முடியும், ஆனால் பிந்தையது எல்லையற்ற படைப்பாற்றல் மற்றும் கட்டுப்பாட்டை வழங்குகிறது.
முக்கிய கூறுகள்: போக்குவரத்து மற்றும் நெறிமுறைகளை நெருக்கமாகப் பார்ப்போம்
குறைந்த-நிலை API இன் சக்தி நெறிமுறைக்கும் டிரான்ஸ்போர்ட்டுக்கும் இடையிலான நேர்த்தியான தொடர்பிலிருந்து வருகிறது. அவை வேறுபட்டவை ஆனால் எந்தவொரு குறைந்த-நிலை asyncio நெட்வொர்க் பயன்பாட்டிலும் பிரிக்க முடியாத கூட்டாளிகள்.
நெறிமுறை: உங்கள் பயன்பாட்டின் மூளை
நெறிமுறை என்பது நீங்கள் எழுதும் ஒரு வகுப்பு. இது asyncio.Protocol
(அல்லது அதன் வகைகளில் ஒன்று) இருந்து பெறுகிறது மற்றும் ஒரு ஒற்றை நெட்வொர்க் இணைப்புக்கான நிலை மற்றும் தர்க்கத்தை கொண்டுள்ளது. இந்த வகுப்பை நீங்களே உருவாக்க வேண்டாம்; நீங்கள் அதை asyncio க்கு வழங்குகிறீர்கள் (எ.கா., loop.create_server
க்கு), மேலும் asyncio ஒவ்வொரு புதிய கிளையண்ட் இணைப்புக்கும் உங்கள் நெறிமுறையின் புதிய நிகழ்வை உருவாக்குகிறது.
உங்கள் நெறிமுறை வகுப்பு நிகழ்வு வளையம் இணைப்பின் வாழ்க்கைச் சுழற்சியில் வெவ்வேறு புள்ளிகளில் அழைக்கும் நிகழ்வு கையாளுதல் முறைகளின் தொகுப்பால் வரையறுக்கப்படுகிறது. மிக முக்கியமானவை:
connection_made(self, transport)
புதிய இணைப்பு வெற்றிகரமாக நிறுவப்பட்டவுடன் சரியாக ஒரு முறை அழைக்கப்படுகிறது. இது உங்கள் நுழைவு புள்ளி. இது இணைப்பைக் குறிக்கும் transport
பொருளை நீங்கள் பெறும் இடம். நீங்கள் எப்போதும் அதற்கான குறிப்பைச் சேமிக்க வேண்டும், பொதுவாக self.transport
ஆக. இடையகங்களை அமைப்பது அல்லது சகா முகவரியை பதிவு செய்வது போன்ற இணைப்புக்குரிய எந்த துவக்கத்தையும் செய்ய இது சிறந்த இடம்.
data_received(self, data)
உங்கள் நெறிமுறையின் இதயம். இணைப்பின் மறுமுனையில் இருந்து புதிய தரவு பெறப்படும்போதெல்லாம் இந்த முறை அழைக்கப்படுகிறது. data
வாதம் ஒரு bytes
பொருள். TCP ஒரு ஸ்ட்ரீம் நெறிமுறை என்பதை நினைவில் கொள்வது மிகவும் முக்கியம், செய்தியின் நெறிமுறை அல்ல. உங்கள் பயன்பாட்டிலிருந்து வரும் ஒரு லாஜிக்கல் செய்தி ஒன்றுக்கும் மேற்பட்ட data_received
அழைப்புகளாகப் பிரிக்கப்படலாம், அல்லது பல சிறிய செய்திகள் ஒரு அழைப்பில் தொகுக்கப்படலாம். உங்கள் குறியீடு இந்த இடையகப்படுத்துதல் மற்றும் பாகுபடுத்தலைக் கையாள வேண்டும்.
connection_lost(self, exc)
இணைப்பு மூடப்படும்போது அழைக்கப்படுகிறது. இது பல காரணங்களுக்காக நடக்கலாம். இணைப்பு சுத்தமாக மூடப்பட்டால் (எ.கா., மறுபக்கம் அதை மூடுகிறது, அல்லது நீங்கள் transport.close()
ஐ அழைக்கிறீர்கள்), exc
None
ஆக இருக்கும். பிழை காரணமாக இணைப்பு மூடப்பட்டால் (எ.கா., நெட்வொர்க் செயலிழப்பு, மீட்டமைத்தல்), பிழையைப் பற்றிய விவரங்களை வழங்கும் ஒரு விதிவிலக்கு பொருளாக exc
இருக்கும். துண்டிக்கப்படுவதைச் சுத்தம் செய்ய, பதிவு செய்ய அல்லது நீங்கள் ஒரு கிளையண்டை உருவாக்கினால் மீண்டும் இணைக்க முயற்சிக்க இதுவே உங்கள் வாய்ப்பு.
eof_received(self)
இது மிகவும் நுட்பமான திரும்ப அழைப்பு. மறுமுனை மேலும் எந்த தரவையும் அனுப்ப மாட்டேன் என்று சமிக்ஞை செய்யும் போது இது அழைக்கப்படுகிறது (எ.கா., POSIX அமைப்பில் shutdown(SHUT_WR)
ஐ அழைப்பதன் மூலம்), ஆனால் தரவு அனுப்ப இணைப்பு திறந்திருக்கலாம். இந்த முறையிலிருந்து True
ஐத் திருப்பினால், போக்குவரத்து மூடப்படும். நீங்கள் False
(இயல்புநிலை) ஐத் திருப்பினால், போக்குவரத்தை நீங்களே பின்னர் மூட வேண்டிய பொறுப்பு உங்களுடையது.
டிரான்ஸ்போர்ட்: தகவல் தொடர்பு சேனல்
டிரான்ஸ்போர்ட் என்பது asyncio வழங்கும் ஒரு பொருள். நீங்கள் அதை உருவாக்க வேண்டாம்; உங்கள் நெறிமுறையின் connection_made
முறையில் அதைப் பெறுவீர்கள். இது அண்டர்லயிங் நெட்வொர்க் சாக்கெட் மற்றும் நிகழ்வு வளையத்தின் I/O திட்டமிடல் ஆகியவற்றின் மீது உயர்-நிலை சுருக்கமாக செயல்படுகிறது. தரவை அனுப்புவதையும் இணைப்பைக் கட்டுப்படுத்துவதையும் கையாள்வது இதன் முக்கிய வேலை.
அதன் முறைகள் மூலம் நீங்கள் டிரான்ஸ்போர்ட்டுடன் தொடர்பு கொள்கிறீர்கள்:
transport.write(data)
தரவு அனுப்புவதற்கான முதன்மை முறை. data
ஒரு bytes
பொருளாக இருக்க வேண்டும். இந்த முறை தடுக்காது. அது உடனடியாக தரவை அனுப்பாது. அதற்கு பதிலாக, அது தரவை ஒரு உள் எழுத இடையகத்தில் வைக்கிறது, மேலும் நிகழ்வு வளையம் அதை பின்னணியில் முடிந்தவரை திறமையாக நெட்வொர்க் மூலம் அனுப்புகிறது.
transport.writelines(list_of_data)
ஒரு நேரத்தில் இடையகத்திற்கு bytes
பொருள்களின் வரிசையை எழுத ஒரு திறமையான வழி, கணினி அழைப்புகளின் எண்ணிக்கையை குறைக்கலாம்.
transport.close()
இது ஒரு கருணையான பணிநிறுத்தத்தைத் தொடங்குகிறது. போக்குவரத்து முதலில் அதன் எழுத இடையகத்தில் மீதமுள்ள எந்த தரவையும் வெளியேற்றி பின்னர் இணைப்பை மூடும். close()
அழைத்த பிறகு வேறு எந்த தரவும் எழுத முடியாது.
transport.abort()
இது கடினமான பணிநிறுத்தத்தை செய்கிறது. இணைப்பு உடனடியாக மூடப்படும், மேலும் எழுத இடையகத்தில் நிலுவையில் உள்ள எந்த தரவும் நிராகரிக்கப்படும். இது விதிவிலக்கான சூழ்நிலைகளில் பயன்படுத்தப்பட வேண்டும்.
transport.get_extra_info(name, default=None)
உற்றுநோக்குவதற்கு மிகவும் பயனுள்ள முறை. சக முகவரி ('peername'
), அண்டர்லயிங் சாக்கெட் பொருள் ('socket'
) அல்லது SSL/TLS சான்றிதழ் தகவல் ('ssl_object'
) போன்ற இணைப்பு பற்றிய தகவல்களைப் பெறலாம்.
கூட்டுறவு உறவு
இந்த வடிவமைப்பின் அழகு என்பது தகவல்களின் தெளிவான, சுழற்சியான ஓட்டம்:
- அமைப்பு: நிகழ்வு வளையம் ஒரு புதிய இணைப்பை ஏற்றுக்கொள்கிறது.
- உருவாக்கம்: வளையம் உங்கள்
Protocol
வகுப்பின் ஒரு நிகழ்வையும், இணைப்பைக் குறிக்கும் ஒருTransport
பொருளையும் உருவாக்குகிறது. - இணைப்பு: வளையம்
your_protocol.connection_made(transport)
ஐ அழைத்து, இரண்டு பொருள்களையும் ஒன்றாக இணைக்கிறது. உங்கள் நெறிமுறைக்கு இப்போது தரவு அனுப்ப ஒரு வழி உள்ளது. - தரவைப் பெறுதல்: நெட்வொர்க் சாக்கெட்டில் தரவு வரும்போது, நிகழ்வு வளையம் விழித்தெழுந்து, தரவைப் படித்து,
your_protocol.data_received(data)
ஐ அழைக்கிறது. - செயலாக்கம்: உங்கள் நெறிமுறையின் தர்க்கம் பெறப்பட்ட தரவை செயலாக்குகிறது.
- தரவை அனுப்புதல்: அதன் தர்க்கத்தின் அடிப்படையில், உங்கள் நெறிமுறை பதில அனுப்ப
self.transport.write(response_data)
ஐ அழைக்கிறது. தரவு இடையகப்படுத்தப்படுகிறது. - பின்னணி I/O: நிகழ்வு வளையம் போக்குவரத்தின் மூலம் இடையகப்படுத்தப்பட்ட தரவை தடுக்காத அனுப்பலைக் கையாளுகிறது.
- பணிநிறுத்தம்: இணைப்பு முடிவடையும் போது, இறுதி துப்புரவுக்காக நிகழ்வு வளையம்
your_protocol.connection_lost(exc)
ஐ அழைக்கிறது.
நடைமுறை உதாரணம்: ஒரு எக்கோ சர்வர் மற்றும் கிளையண்டை உருவாக்குதல்
கோட்பாடு சிறந்தது, ஆனால் போக்குவரத்து மற்றும் நெறிமுறைகளைப் புரிந்துகொள்வதற்கான சிறந்த வழி ஏதாவது உருவாக்குவது. ஒரு கிளாசிக் எக்கோ சர்வர் மற்றும் அதனுடன் தொடர்புடைய கிளையண்டை உருவாக்குவோம். சர்வர் இணைப்புகளை ஏற்கும் மற்றும் அது பெறும் எந்த தரவையும் வெறுமனே திரும்ப அனுப்பும்.
எக்கோ சர்வரின் செயல்படுத்தல்
முதலில், எங்கள் சர்வர் பக்க நெறிமுறையை வரையறுப்போம். இது மிகவும் எளிமையானது, முக்கிய நிகழ்வு கையாளுதலைக் காட்டுகிறது.
import asyncio
class EchoServerProtocol(asyncio.Protocol):
def connection_made(self, transport):
# A new connection is established.
# Get the remote address for logging.
peername = transport.get_extra_info('peername')
print(f"Connection from: {peername}")
# Store the transport for later use.
self.transport = transport
def data_received(self, data):
# Data is received from the client.
message = data.decode()
print(f"Data received: {message.strip()}")
# Echo the data back to the client.
print(f"Echoing back: {message.strip()}")
self.transport.write(data)
def connection_lost(self, exc):
# The connection has been closed.
print("Connection closed.")
# The transport is automatically closed, no need to call self.transport.close() here.
async def main_server():
# Get a reference to the event loop as we plan to run the server indefinitely.
loop = asyncio.get_running_loop()
host = '127.0.0.1'
port = 8888
# The `create_server` coroutine creates and starts the server.
# The first argument is the protocol_factory, a callable that returns a new protocol instance.
# In our case, simply passing the class `EchoServerProtocol` works.
server = await loop.create_server(
lambda: EchoServerProtocol(),
host,
port)
addrs = ', '.join(str(sock.getsockname()) for sock in server.sockets)
print(f'Serving on {addrs}')
# The server runs in the background. To keep the main coroutine alive,
# we can await something that never completes, like a new Future.
# For this example, we'll just run it "forever".
async with server:
await server.serve_forever()
if __name__ == "__main__":
try:
# To run the server:
asyncio.run(main_server())
except KeyboardInterrupt:
print("Server shut down.")
இந்த சர்வர் குறியீட்டில், loop.create_server()
முக்கியமானது. இது குறிப்பிடப்பட்ட ஹோஸ்ட் மற்றும் போர்ட்டுடன் பிணைக்கப்பட்டு, புதிய இணைப்புகளுக்காக கேட்கத் தொடங்க நிகழ்வு வளையத்திற்குச் சொல்கிறது. ஒவ்வொரு உள்வரும் இணைப்புக்கும், அது அந்த குறிப்பிட்ட கிளையண்டிற்காக அர்ப்பணிக்கப்பட்ட புதிய நெறிமுறை நிகழ்வை உருவாக்க எங்கள் protocol_factory
(lambda: EchoServerProtocol()
செயல்பாடு) ஐ அழைக்கிறது.
எக்கோ கிளையன்ட் செயல்படுத்தல்
கிளையன்ட் நெறிமுறை சற்று சிக்கலானது, ஏனெனில் அது அதன் சொந்த நிலையை நிர்வகிக்க வேண்டும்: என்ன செய்தியை அனுப்புவது மற்றும் எப்போது அதன் வேலையை "முடிந்தது" என்று கருதுகிறது. கிளையண்டைத் தொடங்கிய முக்கிய கோரூட்டினுக்கு நிறைவை மீண்டும் சமிக்ஞை செய்ய asyncio.Future
அல்லது asyncio.Event
ஐப் பயன்படுத்துவது ஒரு பொதுவான முறை.
import asyncio
class EchoClientProtocol(asyncio.Protocol):
def __init__(self, message, on_con_lost):
self.message = message
self.on_con_lost = on_con_lost
self.transport = None
def connection_made(self, transport):
self.transport = transport
print(f"Sending: {self.message}")
self.transport.write(self.message.encode())
def data_received(self, data):
print(f"Received echo: {data.decode().strip()}")
def connection_lost(self, exc):
print("The server closed the connection")
# Signal that the connection is lost and the task is complete.
self.on_con_lost.set_result(True)
def eof_received(self):
# This can be called if the server sends an EOF before closing.
print("Received EOF from server.")
async def main_client():
loop = asyncio.get_running_loop()
# The on_con_lost future is used to signal the completion of the client's work.
on_con_lost = loop.create_future()
message = "Hello World!"
host = '127.0.0.1'
port = 8888
# `create_connection` establishes the connection and links the protocol.
try:
transport, protocol = await loop.create_connection(
lambda: EchoClientProtocol(message, on_con_lost),
host,
port)
except ConnectionRefusedError:
print("Connection refused. Is the server running?")
return
# Wait until the protocol signals that the connection is lost.
try:
await on_con_lost
finally:
# Gracefully close the transport.
transport.close()
if __name__ == "__main__":
# To run the client:
# First, start the server in one terminal.
# Then, run this script in another terminal.
asyncio.run(main_client())
இங்கே, loop.create_connection()
என்பது create_server
க்கு கிளையன்ட் பக்க பிரதிநிதி. இது கொடுக்கப்பட்ட முகவரியுடன் இணைக்க முயற்சிக்கிறது. வெற்றிகரமாக இருந்தால், அது எங்கள் EchoClientProtocol
ஐ உருவாக்கி, அதன் connection_made
முறையை அழைக்கிறது. on_con_lost
எதிர்காலத்தைப் பயன்படுத்துவது ஒரு முக்கியமான முறை. main_client
கோரூட்டின் இந்த எதிர்காலத்தை await
செய்கிறது, இது connection_lost
இலிருந்து on_con_lost.set_result(True)
ஐ அழைப்பதன் மூலம் அதன் வேலை முடிந்தது என்று நெறிமுறை சமிக்ஞை செய்யும் வரை அதன் சொந்த செயல்பாட்டை திறம்பட இடைநிறுத்துகிறது.
மேம்பட்ட கருத்துக்கள் மற்றும் நிஜ உலக காட்சிகள்
எக்கோ உதாரணம் அடிப்படைகளை உள்ளடக்கியது, ஆனால் நிஜ உலக நெறிமுறைகள் அரிதாகவே எளிமையானவை. நீங்கள் தவிர்க்க முடியாமல் எதிர்கொள்ளும் சில மேம்பட்ட தலைப்புகளை ஆராய்வோம்.
செய்தி வடிவமைத்தல் மற்றும் இடையகப்படுத்துதலை கையாளுதல்
அடிப்படையான கருத்துக்களுக்குப் பிறகு புரிந்து கொள்ள வேண்டிய மிக முக்கியமான கருத்து என்னவென்றால், TCP என்பது பைட்களின் ஸ்ட்ரீம். உள்ளார்ந்த "செய்தி" எல்லைகள் எதுவும் இல்லை. ஒரு கிளையன்ட் "Hello" மற்றும் பின்னர் "World" ஐ அனுப்பினால், உங்கள் சர்வரின் data_received
ஒருமுறை b'HelloWorld'
உடன், இரண்டு முறை b'Hello'
மற்றும் b'World'
உடன் அல்லது பகுதி தரவுடன் பல முறை அழைக்கப்படலாம்.
இந்த பைட் ஸ்ட்ரீம்களை அர்த்தமுள்ள செய்திகளாக மீண்டும் இணைப்பதற்கு உங்கள் நெறிமுறை பொறுப்பு - "வடிவமைத்தல்". ஒரு பொதுவான உத்தி ஒரு பிரிப்பானைப் பயன்படுத்துவது, அதாவது ஒரு புதிய வரி எழுத்து (\n
).
புதிய வரியைக் கண்டுபிடிக்கும் வரை தரவை இடையகப்படுத்தும் ஒரு மாற்றியமைக்கப்பட்ட நெறிமுறை இங்கே, ஒரு நேரத்தில் ஒரு வரியை செயலாக்குகிறது.
class LineBasedProtocol(asyncio.Protocol):
def __init__(self):
self._buffer = b''
self.transport = None
def connection_made(self, transport):
self.transport = transport
print("Connection established.")
def data_received(self, data):
# Append new data to the internal buffer
self._buffer += data
# Process as many complete lines as we have in the buffer
while b'\n' in self._buffer:
line, self._buffer = self._buffer.split(b'\n', 1)
self.process_line(line.decode().strip())
def process_line(self, line):
# This is where your application logic for a single message goes
print(f"Processing complete message: {line}")
response = f"Processed: {line}\n"
self.transport.write(response.encode())
def connection_lost(self, exc):
print("Connection lost.")
ஓட்டக் கட்டுப்பாட்டை நிர்வகித்தல் (பின் அழுத்தம்)
நெட்வொர்க் அல்லது ரிமோட் சகா அதைக் கையாள்வதை விட உங்கள் பயன்பாடு தரவை போக்குவரத்துக்கு வேகமாக எழுதினால் என்ன நடக்கும்? தரவு போக்குவரத்தின் உள் இடையகத்தில் குவிகிறது. இது சோதிக்கப்படாமல் தொடர்ந்தால், இடையகம் காலவரையின்றி வளரக்கூடும், அனைத்து கிடைக்கக்கூடிய நினைவகத்தையும் உட்கொள்ளும். இந்த பிரச்சினை "பின் அழுத்தம்" இல்லாதது என்று அழைக்கப்படுகிறது.
இதைக் கையாள Asyncio ஒரு பொறிமுறையை வழங்குகிறது. போக்குவரத்து அதன் சொந்த இடையக அளவைக் கண்காணிக்கிறது. இடையகம் ஒரு குறிப்பிட்ட உயர் நீர் குறிக்கு அப்பால் வளரும்போது, நிகழ்வு வளையம் உங்கள் நெறிமுறையின் pause_writing()
முறையை அழைக்கிறது. தரவு அனுப்புவதை நிறுத்த இது உங்கள் பயன்பாட்டிற்கு ஒரு சமிக்ஞை. இடையகம் குறைந்த நீர் குறிக்கு கீழே வடிகட்டிய பிறகு, வளையம் resume_writing()
ஐ அழைக்கிறது, அது மீண்டும் தரவு அனுப்ப பாதுகாப்பானது என்று சமிக்ஞை செய்கிறது.
class FlowControlledProtocol(asyncio.Protocol):
def __init__(self):
self._paused = False
self._data_source = some_data_generator() # Imagine a source of data
self.transport = None
def connection_made(self, transport):
self.transport = transport
self.resume_writing() # Start the writing process
def pause_writing(self):
# The transport buffer is full.
print("Pausing writing.")
self._paused = True
def resume_writing(self):
# The transport buffer has drained.
print("Resuming writing.")
self._paused = False
self._write_more_data()
def _write_more_data(self):
# This is our application's write loop.
while not self._paused:
try:
data = next(self._data_source)
self.transport.write(data)
except StopIteration:
self.transport.close()
break # No more data to send
# Check buffer size to see if we should pause immediately
if self.transport.get_write_buffer_size() > 0:
self.pause_writing()
TCP க்கு அப்பால்: பிற போக்குவரத்துகள்
TCP மிகவும் பொதுவான பயன்பாட்டு நிகழ்வாக இருந்தாலும், போக்குவரத்து/நெறிமுறை முறை அதற்குக் கட்டுப்படுத்தப்படவில்லை. Asyncio பிற தகவல் தொடர்பு வகைகளுக்கான சுருக்கங்களை வழங்குகிறது:
- UDP: இணைப்பு இல்லாத தகவல்தொடர்புக்கு, நீங்கள்
loop.create_datagram_endpoint()
ஐப் பயன்படுத்துகிறீர்கள். இது உங்களுக்குDatagramTransport
ஐ வழங்குகிறது மற்றும்datagram_received(data, addr)
மற்றும்error_received(exc)
போன்ற முறைகளுடன்asyncio.DatagramProtocol
ஐ செயல்படுத்துவீர்கள். - SSL/TLS: குறியாக்கத்தைச் சேர்ப்பது நம்பமுடியாத அளவிற்கு நேரடியானது.
ssl.SSLContext
பொருளைloop.create_server()
அல்லதுloop.create_connection()
க்கு அனுப்புகிறீர்கள். Asyncio TLS கைக்குலுக்கலை தானாகவே கையாளுகிறது, மேலும் உங்களுக்கு பாதுகாப்பான போக்குவரத்து கிடைக்கும். உங்கள் நெறிமுறை குறியீடு எதுவும் மாறத் தேவையில்லை. - துணை செயல்முறைகள்: அவர்களின் தரநிலை I/O குழாய்கள் வழியாக குழந்தை செயல்முறைகளுடன் தொடர்புகொள்வதற்கு,
loop.subprocess_exec()
மற்றும்loop.subprocess_shell()
ஐasyncio.SubprocessProtocol
உடன் பயன்படுத்தலாம். இது குழந்தை செயல்முறைகளை முழு ஒத்திசைவற்ற, தடுக்காத வழியில் நிர்வகிக்க உங்களை அனுமதிக்கிறது.
மூலோபாய முடிவு: போக்குவரத்து vs. ஸ்ட்ரீம்களை எப்போது பயன்படுத்துவது
உங்கள் வசம் இரண்டு சக்திவாய்ந்த APIகளுடன், ஒரு முக்கிய கட்டடக்கலை முடிவு வேலைக்கு ஏற்றதைத் தேர்ந்தெடுப்பது. உங்களுக்கு உதவ ஒரு வழிகாட்டி இங்கே.
ஸ்ட்ரீம்களைத் தேர்ந்தெடுக்கவும் (StreamReader
/StreamWriter
) எப்போது...
- உங்கள் நெறிமுறை எளிமையானது மற்றும் கோரிக்கை-பதில் அடிப்படையிலானது. தர்க்கம் "ஒரு கோரிக்கையைப் படிக்கவும், அதைச் செயல்படுத்தவும், ஒரு பதில எழுதவும்" என்றால், ஸ்ட்ரீம்கள் சரியானவை.
- நன்கு அறியப்பட்ட, வரி அடிப்படையிலான அல்லது நிலையான நீள செய்தி நெறிமுறைக்கு நீங்கள் ஒரு கிளையண்டை உருவாக்குகிறீர்கள். எடுத்துக்காட்டாக, ஒரு ரெடிஸ் சர்வர் அல்லது எளிய FTP சர்வர்டன் தொடர்புகொள்வது.
- குறியீடு வாசிப்பு மற்றும் நேரியல், கட்டாய பாணிக்கு நீங்கள் முன்னுரிமை அளித்தால். ஸ்ட்ரீம்களுடன் கூடிய
async/await
தொடரியல் ஒத்திசைவற்ற நிரலாக்கத்திற்கு புதிய டெவலப்பர்கள் புரிந்து கொள்ள பெரும்பாலும் எளிதானது. - விரைவான முன்மாதிரி முக்கியமானது. நீங்கள் ஒரு எளிய கிளையண்டை அல்லது சேவையகத்தை சில வரிக் குறியீட்டில் இயக்கலாம் மற்றும் இயக்கலாம்.
போக்குவரத்துகள் மற்றும் நெறிமுறைகளைத் தேர்ந்தெடுக்கவும் எப்போது...
- சிக்கலான அல்லது தனிப்பயன் நெட்வொர்க் நெறிமுறையை புதிதாக செயல்படுத்தினால். இது முதன்மை பயன்பாட்டு வழக்கு. கேமிங், நிதி தரவு ஊட்டங்கள், IoT சாதனங்கள் அல்லது பியர்-டு-பியர் பயன்பாடுகளுக்கான நெறிமுறைகளைப் பற்றி சிந்தியுங்கள்.
- உங்கள் நெறிமுறை அதிக நிகழ்வு-உந்துதல் மற்றும் முற்றிலும் கோரிக்கை-பதில் அல்ல. சர்வர் எந்த நேரத்திலும் கிளையண்டிற்கு வேண்டப்படாத செய்திகளை அனுப்ப முடியுமானால், நெறிமுறைகளின் திரும்ப அழைப்பு அடிப்படையிலான இயல்பு மிகவும் இயற்கையான பொருத்தம்.
- உங்களுக்கு அதிகபட்ச செயல்திறன் மற்றும் குறைந்த மேலீடு தேவைப்பட்டால். நெறிமுறைகள் உங்களுக்கு நிகழ்வு வளையத்திற்கு நேரடியான பாதையை வழங்குகின்றன, ஸ்ட்ரீம்ஸ் API உடன் தொடர்புடைய சில மேலீடுதைத் தவிர்க்கின்றன.
- இணைப்பின் மீது உங்களுக்கு நல்ல கட்டுப்பாடு தேவை. இதில் கைமுறை இடையக மேலாண்மை, தெளிவான ஓட்டக் கட்டுப்பாடு (
pause/resume_writing
), மற்றும் இணைப்பு வாழ்க்கைச் சுழற்சியின் விரிவான கையாளுதல் ஆகியவை அடங்கும். - நீங்கள் ஒரு நெட்வொர்க் கட்டமைப்பு அல்லது லைப்ரரியை உருவாக்கினால். பிற டெவலப்பர்களுக்கு நீங்கள் ஒரு கருவியை வழங்கினால், நெறிமுறை/போக்குவரத்து API இன் வலுவான மற்றும் நெகிழ்வான இயல்பு பெரும்பாலும் சரியான அடித்தளம்.
முடிவுரை: Asyncio இன் அடித்தளத்தை ஏற்றுக்கொள்வது
பைத்தானின் asyncio
லைப்ரரி அடுக்கு வடிவமைப்பின் தலைசிறந்த படைப்பு. உயர்-நிலை ஸ்ட்ரீம்கள் API அணுகக்கூடிய மற்றும் உற்பத்தித்திறன் நுழைவு புள்ளியை வழங்கும் அதே வேளையில், குறைந்த-நிலை போக்குவரத்து மற்றும் நெறிமுறை API என்பது asyncio இன் நெட்வொர்க்கிங் திறன்களின் உண்மையான, சக்திவாய்ந்த அடித்தளத்தைக் குறிக்கிறது. I/O பொறிமுறையை (போக்குவரத்து) பயன்பாட்டு தர்க்கத்திலிருந்து (நெறிமுறை) பிரிப்பதன் மூலம், இது அதிநவீன நெட்வொர்க் பயன்பாடுகளை உருவாக்குவதற்கான வலுவான, அளவிடக்கூடிய மற்றும் நம்பமுடியாத நெகிழ்வான மாதிரியை வழங்குகிறது.
இந்த குறைந்த-நிலை சுருக்கத்தைப் புரிந்துகொள்வது ஒரு கல்விப் பயிற்சி மட்டுமல்ல; இது ஒரு நடைமுறை திறன், இது எளிய கிளையண்டுகள் மற்றும் சேவையகங்களுக்கு அப்பால் நகர உங்களுக்கு அதிகாரம் அளிக்கிறது. இது எந்த நெட்வொர்க் நெறிமுறையையும் சமாளிக்க உங்களுக்கு நம்பிக்கையை அளிக்கிறது, அழுத்தத்தின் கீழ் செயல்திறனை மேம்படுத்துவதற்கான கட்டுப்பாடு மற்றும் பைத்தானில் அடுத்த தலைமுறை உயர் செயல்திறன், ஒத்திசைவற்ற சேவைகளை உருவாக்கும் திறன் ஆகியவற்றை வழங்குகிறது. அடுத்த முறை நீங்கள் ஒரு சவாலான நெட்வொர்க்கிங் சிக்கலை எதிர்கொள்ளும்போது, மேற்பரப்பின் கீழே இருக்கும் சக்தியை நினைவில் கொள்ளுங்கள், மேலும் போக்குவரத்து மற்றும் நெறிமுறைகளின் நேர்த்தியான ஜோடியை அடைய தயங்க வேண்டாம்.